/* $Id: VBoxMPVidPn.cpp $ */
/** @file
 * VBox WDDM Miniport driver
 */

/*
 * Copyright (C) 2011-2020 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 */
 
#include "VBoxMPWddm.h"
#include "wddm/VBoxMPTypes.h"
#include "VBoxMPVidPn.h"
#include "VBoxMPVModes.h"
#include "VBoxMPMisc.h"
#include "trace.h"
#include "asm.h"

void VBoxVidPnAllocDataInit(VBOXWDDM_ALLOC_DATA *pData, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
{
    memset(pData, 0, sizeof (*pData));
    pData->SurfDesc.VidPnSourceId = VidPnSourceId;
    pData->Addr.offVram = VBOXVIDEOOFFSET_VOID;
}

void VBoxVidPnSourceInit(PVBOXWDDM_SOURCE pSource, const D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, UINT8 u8SyncState)
{
    memset(pSource, 0, sizeof (*pSource));
    VBoxVidPnAllocDataInit(&pSource->AllocData, VidPnSourceId);
    pSource->u8SyncState = (u8SyncState & VBOXWDDM_HGSYNC_F_SYNCED_ALL);
}

void VBoxVidPnTargetInit(PVBOXWDDM_TARGET pTarget, const D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId, UINT8 u8SyncState)
{
    memset(pTarget, 0, sizeof (*pTarget));
    pTarget->u32Id = VidPnTargetId;
    pTarget->VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
    pTarget->u8SyncState = (u8SyncState & VBOXWDDM_HGSYNC_F_SYNCED_ALL);
}

void VBoxVidPnSourcesInit(PVBOXWDDM_SOURCE pSources, UINT32 cScreens, UINT8 u8SyncState)
{
    for (UINT32 i = 0; i < cScreens; ++i)
        VBoxVidPnSourceInit(&pSources[i], i, u8SyncState);
}

void VBoxVidPnTargetsInit(PVBOXWDDM_TARGET pTargets, UINT32 cScreens, UINT8 u8SyncState)
{
    for (UINT32 i = 0; i < cScreens; ++i)
        VBoxVidPnTargetInit(&pTargets[i], i, u8SyncState);
}

static BOOLEAN vboxVidPnIsPathSupported(PVBOXMP_DEVEXT pDevExt,
    const D3DKMDT_VIDPN_PRESENT_PATH *pNewVidPnPresentPathInfo)
{
    if (!pDevExt->fComplexTopologiesEnabled &&
        pNewVidPnPresentPathInfo->VidPnSourceId !=
        pNewVidPnPresentPathInfo->VidPnTargetId) {
        LOGI("unsupported source(%d)->target(%d) pair\n",
             pNewVidPnPresentPathInfo->VidPnSourceId,
             pNewVidPnPresentPathInfo->VidPnTargetId);
        return FALSE;
    }

    /*
     * ImportanceOrdinal does not matter for now
     *  pNewVidPnPresentPathInfo->ImportanceOrdinal
     */

    if (pNewVidPnPresentPathInfo->ContentTransformation.Scaling != D3DKMDT_VPPS_UNPINNED &&
        pNewVidPnPresentPathInfo->ContentTransformation.Scaling != D3DKMDT_VPPS_IDENTITY &&
        pNewVidPnPresentPathInfo->ContentTransformation.Scaling != D3DKMDT_VPPS_NOTSPECIFIED) {
        LOGW("unsupported Scaling (%d)\n",
             pNewVidPnPresentPathInfo->ContentTransformation.Scaling);
        return FALSE;
    }

    if (!pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport.Identity ||
        pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport.Centered ||
        pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport.Stretched) {
        LOGW("unsupported Scaling support\n");
        return FALSE;
    }

    if (pNewVidPnPresentPathInfo->ContentTransformation.Rotation != D3DKMDT_VPPR_UNPINNED &&
        pNewVidPnPresentPathInfo->ContentTransformation.Rotation != D3DKMDT_VPPR_IDENTITY &&
        pNewVidPnPresentPathInfo->ContentTransformation.Rotation != D3DKMDT_VPPR_NOTSPECIFIED) {
        LOGW("unsupported rotation (%d)\n",
             pNewVidPnPresentPathInfo->ContentTransformation.Rotation);
        return FALSE;
    }

    if (!pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Identity ||
        pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Rotate90 ||
        pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Rotate180 ||
        pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Rotate270) {
        LOGW("unsupported RotationSupport\n");
        return FALSE;
    }

    if (pNewVidPnPresentPathInfo->VisibleFromActiveTLOffset.cx ||
        pNewVidPnPresentPathInfo->VisibleFromActiveTLOffset.cy) {
        LOGW("Non-zero TLOffset: cx(%d), cy(%d)\n",
             pNewVidPnPresentPathInfo->VisibleFromActiveTLOffset.cx,
             pNewVidPnPresentPathInfo->VisibleFromActiveTLOffset.cy);
        return FALSE;
    }

    if (pNewVidPnPresentPathInfo->VisibleFromActiveBROffset.cx ||
        pNewVidPnPresentPathInfo->VisibleFromActiveBROffset.cy) {
        LOGW("Non-zero BROffset: cx(%d), cy(%d)\n",
             pNewVidPnPresentPathInfo->VisibleFromActiveBROffset.cx,
             pNewVidPnPresentPathInfo->VisibleFromActiveBROffset.cy);
        return FALSE;
    }

    if (pNewVidPnPresentPathInfo->VidPnTargetColorBasis != D3DKMDT_CB_SRGB &&
        pNewVidPnPresentPathInfo->VidPnTargetColorBasis != D3DKMDT_CB_UNINITIALIZED) {
        LOGW("unsupported VidPnTargetColorBasis (%d)\n",
             pNewVidPnPresentPathInfo->VidPnTargetColorBasis);
        return FALSE;
    }

    /* channels?
     * pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.FirstChannel;
     * pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.SecondChannel;
     * pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.ThirdChannel;
     * we definitely not support fourth channel
     */
    if (pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.FourthChannel) {
        LOGW("Non-zero FourthChannel (%d)\n",
             pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.FourthChannel);
        return FALSE;
    }

    /* Content (D3DKMDT_VPPC_GRAPHICS, _NOTSPECIFIED, _VIDEO), does not matter for now
     * pNewVidPnPresentPathInfo->Content
     */
    /* not support copy protection for now */
    if (pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionType != D3DKMDT_VPPMT_NOPROTECTION &&
        pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionType != D3DKMDT_VPPMT_UNINITIALIZED) {
        LOGW("Copy protection not supported CopyProtectionType(%d)\n",
             pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionType);
        return FALSE;
    }

    if (pNewVidPnPresentPathInfo->CopyProtection.APSTriggerBits) {
        LOGW("Copy protection not supported APSTriggerBits(%d)\n",
             pNewVidPnPresentPathInfo->CopyProtection.APSTriggerBits);
        return FALSE;
    }

    D3DKMDT_VIDPN_PRESENT_PATH_COPYPROTECTION_SUPPORT tstCPSupport = {0};
    tstCPSupport.NoProtection = 1;
    if (memcmp(&tstCPSupport,
        &pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionSupport,
        sizeof(tstCPSupport))) {
        LOGW("Copy protection support (0x%x)",
             *((UINT*)&pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionSupport));
        return FALSE;
    }

    if (pNewVidPnPresentPathInfo->GammaRamp.Type != D3DDDI_GAMMARAMP_DEFAULT &&
        pNewVidPnPresentPathInfo->GammaRamp.Type != D3DDDI_GAMMARAMP_UNINITIALIZED) {
        LOGW("Unsupported GammaRamp.Type (%d)\n",
             pNewVidPnPresentPathInfo->GammaRamp.Type);
        return FALSE;
    }

    if (pNewVidPnPresentPathInfo->GammaRamp.DataSize != 0) {
        LOGW("Warning: non-zero GammaRamp.DataSize (%lld), treating as supported",
             pNewVidPnPresentPathInfo->GammaRamp.DataSize);
    }

    return TRUE;
}

NTSTATUS vboxVidPnQueryPinnedTargetMode(D3DKMDT_HVIDPN hVidPn,
        const DXGK_VIDPN_INTERFACE* pVidPnInterface,
        D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId, RTRECTSIZE *pSize)
{
    D3DKMDT_HVIDPNTARGETMODESET hCurVidPnTargetModeSet;
    const DXGK_VIDPNTARGETMODESET_INTERFACE *pCurVidPnTargetModeSetInterface;
    NTSTATUS Status;

    pSize->cx = 0;
    pSize->cy = 0;
    Status = pVidPnInterface->pfnAcquireTargetModeSet(hVidPn,
                        VidPnTargetId,
                        &hCurVidPnTargetModeSet,
                        &pCurVidPnTargetModeSetInterface);
    if (!NT_SUCCESS(Status)) {
        LOGE("pfnAcquireTargetModeSet failed Status(0x%x)", Status);
        return Status;
    }

    CONST D3DKMDT_VIDPN_TARGET_MODE* pPinnedVidPnTargetModeInfo;
    Status = pCurVidPnTargetModeSetInterface->pfnAcquirePinnedModeInfo(
                    hCurVidPnTargetModeSet, &pPinnedVidPnTargetModeInfo);
    if (Status == STATUS_GRAPHICS_MODE_NOT_PINNED) {
        pPinnedVidPnTargetModeInfo = NULL;
        Status = STATUS_SUCCESS;
    } else if (!NT_SUCCESS(Status)) {
        LOGW("pfnAcquirePinnedModeInfo failed Status(0x%x)", Status);
    } else {
        pSize->cx = pPinnedVidPnTargetModeInfo->VideoSignalInfo.ActiveSize.cx;
        pSize->cy = pPinnedVidPnTargetModeInfo->VideoSignalInfo.ActiveSize.cy;
        pCurVidPnTargetModeSetInterface->pfnReleaseModeInfo(
                            hCurVidPnTargetModeSet, pPinnedVidPnTargetModeInfo);
    }

    pVidPnInterface->pfnReleaseTargetModeSet(
                                hVidPn, hCurVidPnTargetModeSet);

    return Status;
}

NTSTATUS vboxVidPnQueryPinnedSourceMode(D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
        D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, RTRECTSIZE *pSize)
{
    D3DKMDT_HVIDPNSOURCEMODESET hCurVidPnSourceModeSet;
    const DXGK_VIDPNSOURCEMODESET_INTERFACE *pCurVidPnSourceModeSetInterface;
    pSize->cx = 0;
    pSize->cy = 0;
    NTSTATUS Status = pVidPnInterface->pfnAcquireSourceModeSet(hVidPn,
                        VidPnSourceId,
                        &hCurVidPnSourceModeSet,
                        &pCurVidPnSourceModeSetInterface);
    if (!NT_SUCCESS(Status)) {
        LOGE("pfnAcquireSourceModeSet failed Status(0x%x)", Status);
        return Status;
    }

    CONST D3DKMDT_VIDPN_SOURCE_MODE* pPinnedVidPnSourceModeInfo;
    Status = pCurVidPnSourceModeSetInterface->pfnAcquirePinnedModeInfo(
                    hCurVidPnSourceModeSet, &pPinnedVidPnSourceModeInfo);
    if (Status == STATUS_GRAPHICS_MODE_NOT_PINNED) {
        pPinnedVidPnSourceModeInfo = NULL;
        Status = STATUS_SUCCESS;
    } else if (!NT_SUCCESS(Status)) {
        LOGW("pfnAcquirePinnedModeInfo failed Status(0x%x)", Status);
    }
    else {
        pSize->cx = pPinnedVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize.cx;
        pSize->cy = pPinnedVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize.cy;
        pCurVidPnSourceModeSetInterface->pfnReleaseModeInfo(
                            hCurVidPnSourceModeSet, pPinnedVidPnSourceModeInfo);
    }

    pVidPnInterface->pfnReleaseSourceModeSet(
                                hVidPn, hCurVidPnSourceModeSet);

    return Status;
}

NTSTATUS VBoxVidPnIsSupported(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPN hVidPn, BOOLEAN *pfSupported)
{
    /* According Microsoft Docs we must return pfSupported = TRUE here if hVidPn is NULL, as
     * the display adapter can always be configured to display nothing. */
    if (hVidPn == NULL) {
        LOGW("VBoxVidPnIsSupported vidPn handle is null\n");
        *pfSupported = TRUE;
        return STATUS_SUCCESS;
    }

    *pfSupported = FALSE;

    const DXGK_VIDPN_INTERFACE *pVidPnInterface = NULL;
    NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(hVidPn, 
                                    DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
    if (!NT_SUCCESS(Status)) {
        LOGE("DxgkCbQueryVidPnInterface failed Status(0x%x)\n", Status);
        return Status;
    }

    D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
    const DXGK_VIDPNTOPOLOGY_INTERFACE *pVidPnTopologyInterface;
    Status = pVidPnInterface->pfnGetTopology(hVidPn, &hVidPnTopology,
                                             &pVidPnTopologyInterface);
    if (!NT_SUCCESS(Status)) {
        LOGE("pfnGetTopology failed Status(0x%x)\n", Status);
        return Status;
    }

    VBOXVIDPN_PATH_ITER PathIter;
    const D3DKMDT_VIDPN_PRESENT_PATH *pPath;
    VBOXCMDVBVA_SCREENMAP_DECL(UINT32, aVisitedTargetMap);

    memset(aVisitedTargetMap, 0, sizeof(aVisitedTargetMap));

    BOOLEAN fSupported = TRUE;
    /* collect info first */
    VBoxVidPnPathIterInit(&PathIter, hVidPnTopology, pVidPnTopologyInterface);
    while ((pPath = VBoxVidPnPathIterNext(&PathIter)) != NULL) {
        D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId = pPath->VidPnSourceId;
        D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId = pPath->VidPnTargetId;
        /* actually vidpn topology should contain only one target info, right? */
        ASMBitSet(aVisitedTargetMap, VidPnTargetId);

        if (!vboxVidPnIsPathSupported(pDevExt, pPath)) {
            fSupported = FALSE;
            break;
        }

        RTRECTSIZE TargetSize;
        RTRECTSIZE SourceSize;
        Status = vboxVidPnQueryPinnedTargetMode(hVidPn, pVidPnInterface,
                                                VidPnTargetId, &TargetSize);
        if (!NT_SUCCESS(Status)) {
            LOGE("vboxVidPnQueryPinnedTargetMode failed %#x\n", Status);
            break;
        }

        Status = vboxVidPnQueryPinnedSourceMode(hVidPn, pVidPnInterface,
                                                VidPnSourceId, &SourceSize);
        if (!NT_SUCCESS(Status)) {
            LOGE("vboxVidPnQueryPinnedSourceMode failed %#x\n", Status);
            break;
        }

        if (memcmp(&TargetSize, &SourceSize, sizeof (TargetSize)) &&
            TargetSize.cx) {
            if (!SourceSize.cx) {
                LOGE("not expected?");
            }

            fSupported = FALSE;
            break;
        }
    }

    VBoxVidPnPathIterTerm(&PathIter);

    if (!NT_SUCCESS(Status)) {
        goto done;
    }

    Status = VBoxVidPnPathIterStatus(&PathIter);
    if (!NT_SUCCESS(Status)) {
        LOGE("PathIter failed Status()0x%x\n", Status);
        goto done;
    }

    *pfSupported = fSupported;

done:
    return Status;
}

static NTSTATUS vboxVidPnPopulateVideoSignalInfo(D3DKMDT_VIDEO_SIGNAL_INFO *pVsi,
        const RTRECTSIZE *pResolution,
        ULONG VSync)
{
    NTSTATUS Status = STATUS_SUCCESS;

    pVsi->VideoStandard  = D3DKMDT_VSS_OTHER;
    pVsi->ActiveSize.cx = pResolution->cx;
    pVsi->ActiveSize.cy = pResolution->cy;
    pVsi->TotalSize = pVsi->ActiveSize;
    if (VBOXWDDM_IS_DISPLAYONLY()) {
        /* VSYNC is not implemented in display-only mode (#8228).
         * In this case Windows checks that frequencies are not specified.
         */
        LOGW("VBOXWDDM_IS_DISPLAYONLY()=1\n");
        pVsi->VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
        pVsi->VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
        pVsi->PixelRate = D3DKMDT_FREQUENCY_NOTSPECIFIED;
        pVsi->HSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
        pVsi->HSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
    } else {
        LOGW("VBOXWDDM_IS_DISPLAYONLY()=0\n");
        pVsi->VSyncFreq.Numerator = VSync * 1000;
        pVsi->VSyncFreq.Denominator = 1000;
        pVsi->PixelRate = pVsi->TotalSize.cx * pVsi->TotalSize.cy * VSync;
        pVsi->HSyncFreq.Numerator = (UINT)((VSync * pVsi->TotalSize.cy) * 1000);
        pVsi->HSyncFreq.Denominator = 1000;
    }
    pVsi->ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE;

    return Status;
}

static void vboxVidPnPopulateMonitorModeInfo(D3DKMDT_MONITOR_SOURCE_MODE *pMonitorSourceMode, const RTRECTSIZE *pResolution, ULONG VSync)
{
    vboxVidPnPopulateVideoSignalInfo(&pMonitorSourceMode->VideoSignalInfo, pResolution, VSync);
    pMonitorSourceMode->ColorBasis = D3DKMDT_CB_SRGB;
    pMonitorSourceMode->ColorCoeffDynamicRanges.FirstChannel = 8;
    pMonitorSourceMode->ColorCoeffDynamicRanges.SecondChannel = 8;
    pMonitorSourceMode->ColorCoeffDynamicRanges.ThirdChannel = 8;
    pMonitorSourceMode->ColorCoeffDynamicRanges.FourthChannel = 0;
    pMonitorSourceMode->Origin = D3DKMDT_MCO_DRIVER;
    pMonitorSourceMode->Preference = D3DKMDT_MP_NOTPREFERRED;
}

static NTSTATUS vboxVidPnMonitorModeSetByVSync(D3DKMDT_HMONITORSOURCEMODESET hVidPnModeSet,
        const DXGK_MONITORSOURCEMODESET_INTERFACE *pVidPnModeSetInterface,
        const CR_SORTARRAY *pArray, RTRECTSIZE *size, ULONG VSync)
{
    D3DKMDT_MONITOR_SOURCE_MODE *pVidPnModeInfo;
    NTSTATUS Status = pVidPnModeSetInterface->pfnCreateNewModeInfo(hVidPnModeSet, &pVidPnModeInfo);
    if (!NT_SUCCESS(Status)) {
        LOGE("pfnCreateNewModeInfo failed, Status 0x%x\n", Status);
        return Status;
    }

    vboxVidPnPopulateMonitorModeInfo(pVidPnModeInfo, size, VSync);

    Status = pVidPnModeSetInterface->pfnAddMode(hVidPnModeSet, pVidPnModeInfo);
    if (!NT_SUCCESS(Status)) {
        LOGE("pfnAddMode (%d x %d) failed, Status 0x%x\n", size->cx, size->cy, Status);
        pVidPnModeSetInterface->pfnReleaseModeInfo(hVidPnModeSet, pVidPnModeInfo);
        return Status;
    }

    return STATUS_SUCCESS;
}

static NTSTATUS vboxVidPnMonitorModeSetFromArray(D3DKMDT_HMONITORSOURCEMODESET hVidPnModeSet,
        const DXGK_MONITORSOURCEMODESET_INTERFACE *pVidPnModeSetInterface,
        const CR_SORTARRAY *pArray)
{
    for (UINT32 i = 0; i < CrSaGetSize(pArray); ++i) {
        RTRECTSIZE size = CR_U642RSIZE(CrSaGetVal(pArray, i));
        NTSTATUS Status = vboxVidPnMonitorModeSetByVSync(hVidPnModeSet, pVidPnModeSetInterface,
            pArray, &size, VBOXWDDM_DEFAULT_REFRESH_RATE);
        if (!NT_SUCCESS(Status)) {
            LOGE("Set mode (%d x %d) VSync: %d failed, Status 0x%x\n", size.cx, size.cy, Status);
        }
        Status = vboxVidPnMonitorModeSetByVSync(hVidPnModeSet, pVidPnModeSetInterface,
            pArray, &size, VBOXWDDM_DECODER_REFRESH_RATE);
        if (!NT_SUCCESS(Status)) {
            LOGE("Set mode (%d x %d) VSync: %d failed, Status 0x%x\n", size.cx, size.cy, Status);
        }
    }

    return STATUS_SUCCESS;
}

static NTSTATUS vboxVidPnCheckMonitorModes(PVBOXMP_DEVEXT pDevExt,
            UINT32 u32Target, const CR_SORTARRAY *pSupportedModes = NULL)
{
    NTSTATUS Status;
    CONST DXGK_MONITOR_INTERFACE *pMonitorInterface;
    Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryMonitorInterface(
             pDevExt->u.primary.DxgkInterface.DeviceHandle,
             DXGK_MONITOR_INTERFACE_VERSION_V1, &pMonitorInterface);
    if (!NT_SUCCESS(Status)) {
        LOGE("DxgkCbQueryMonitorInterface failed, Status()0x%x\n", Status);
        return Status;
    }

    D3DKMDT_HMONITORSOURCEMODESET hVidPnModeSet;
    CONST DXGK_MONITORSOURCEMODESET_INTERFACE *pVidPnModeSetInterface;

    if (!pSupportedModes) {
        pSupportedModes = VBoxWddmVModesGet(pDevExt, u32Target);
    }

    CR_SORTARRAY DiffModes;
    int rc = CrSaInit(&DiffModes, CrSaGetSize(pSupportedModes));
    if (!RT_SUCCESS(rc)) {
        LOGE("CrSaInit failed\n");
        return STATUS_NO_MEMORY;
    }

    Status = pMonitorInterface->pfnAcquireMonitorSourceModeSet(
                            pDevExt->u.primary.DxgkInterface.DeviceHandle,
                            u32Target,
                            &hVidPnModeSet,
                            &pVidPnModeSetInterface);
    if (!NT_SUCCESS(Status)) {
        LOGE("DxgkCbQueryMonitorInterface failed, Status()0x%x\n", Status);
        CrSaCleanup(&DiffModes);
        return Status;
    }

    VBOXVIDPN_MONITORMODE_ITER Iter;
    const D3DKMDT_MONITOR_SOURCE_MODE *pVidPnModeInfo;

    rc = CrSaClone(pSupportedModes, &DiffModes);
    if (!RT_SUCCESS(rc)) {
        LOGE("CrSaClone failed\n");
        Status = STATUS_NO_MEMORY;
        goto done;
    }

    VBoxVidPnMonitorModeIterInit(&Iter, hVidPnModeSet, pVidPnModeSetInterface);

    while ((pVidPnModeInfo = VBoxVidPnMonitorModeIterNext(&Iter)) != NULL) {
        RTRECTSIZE size;
        size.cx = pVidPnModeInfo->VideoSignalInfo.ActiveSize.cx;
        size.cy = pVidPnModeInfo->VideoSignalInfo.ActiveSize.cy;
        CrSaRemove(&DiffModes, CR_RSIZE2U64(size));
        LOGI("mode (%d x %d) is already in monitor modeset\n", size.cx, size.cy);
    }

    VBoxVidPnMonitorModeIterTerm(&Iter);

    Status = VBoxVidPnMonitorModeIterStatus(&Iter);
    if (!NT_SUCCESS(Status)) {
        LOGE("iter status failed %#x\n", Status);
        goto done;
    }

    LOGI("Adding %d additional modes to monitor modeset\n", CrSaGetSize(&DiffModes));

    Status = vboxVidPnMonitorModeSetFromArray(hVidPnModeSet, pVidPnModeSetInterface, &DiffModes);
    if (!NT_SUCCESS(Status)) {
        LOGE("vboxVidPnMonitorModeSetFromArray failed %#x\n", Status);
        goto done;
    }

done:
    NTSTATUS rcNt2 = pMonitorInterface->pfnReleaseMonitorSourceModeSet(
            pDevExt->u.primary.DxgkInterface.DeviceHandle, hVidPnModeSet);
    if (!NT_SUCCESS(rcNt2)) {
        LOGE("pfnReleaseMonitorSourceModeSet failed rcNt2(0x%x)", rcNt2);
    }

    CrSaCleanup(&DiffModes);

    return Status;
}

static NTSTATUS vboxVidPnPathAdd(D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
        const D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, const D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId,
        D3DKMDT_VIDPN_PRESENT_PATH_IMPORTANCE enmImportance)
{
    D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
    const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
    NTSTATUS Status = pVidPnInterface->pfnGetTopology(hVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
    if (!NT_SUCCESS(Status)) {
        LOGE("pfnGetTopology failed status (0x%x)\n", Status);
        return Status;
    }

    D3DKMDT_VIDPN_PRESENT_PATH *pNewVidPnPresentPathInfo;
    Status = pVidPnTopologyInterface->pfnCreateNewPathInfo(hVidPnTopology, &pNewVidPnPresentPathInfo);
    if (!NT_SUCCESS(Status)) {
        LOGE("pfnCreateNewPathInfo failed status (0x%x)\n", Status);
        return Status;
    }

    pNewVidPnPresentPathInfo->VidPnSourceId = VidPnSourceId;
    pNewVidPnPresentPathInfo->VidPnTargetId = VidPnTargetId;
    pNewVidPnPresentPathInfo->ImportanceOrdinal = enmImportance;
    pNewVidPnPresentPathInfo->ContentTransformation.Scaling = D3DKMDT_VPPS_IDENTITY;
    memset(&pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport,
            0, sizeof (pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport));
    pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport.Identity = 1;
    pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport.Centered = 0;
    pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport.Stretched = 0;
    pNewVidPnPresentPathInfo->ContentTransformation.Rotation = D3DKMDT_VPPR_IDENTITY;
    pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Identity = 1;
    pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Rotate180 = 0;
    pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Rotate270 = 0;
    pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Rotate90 = 0;
    pNewVidPnPresentPathInfo->VisibleFromActiveTLOffset.cx = 0;
    pNewVidPnPresentPathInfo->VisibleFromActiveTLOffset.cy = 0;
    pNewVidPnPresentPathInfo->VisibleFromActiveBROffset.cx = 0;
    pNewVidPnPresentPathInfo->VisibleFromActiveBROffset.cy = 0;
    pNewVidPnPresentPathInfo->VidPnTargetColorBasis = D3DKMDT_CB_SRGB; /** @todo how does it matters? */
    pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.FirstChannel =  8;
    pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.SecondChannel =  8;
    pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.ThirdChannel =  8;
    pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.FourthChannel =  0;
    pNewVidPnPresentPathInfo->Content = D3DKMDT_VPPC_GRAPHICS;
    pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionType = D3DKMDT_VPPMT_UNINITIALIZED;
    pNewVidPnPresentPathInfo->CopyProtection.APSTriggerBits = 0;
    memset(&pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionSupport, 0,
           sizeof(pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionSupport));
    memset (&pNewVidPnPresentPathInfo->GammaRamp, 0, sizeof (pNewVidPnPresentPathInfo->GammaRamp));
    Status = pVidPnTopologyInterface->pfnAddPath(hVidPnTopology, pNewVidPnPresentPathInfo);
    if (!NT_SUCCESS(Status)) {
        LOGE("pfnAddPath failed status (0x%x)\n", Status);
        pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pNewVidPnPresentPathInfo);
    }

    LOGW("Recommended Path (%d->%d)\n", VidPnSourceId, VidPnTargetId);

    return Status;
}

static NTSTATUS vboxVidPnPopulateTargetModeInfo(D3DKMDT_VIDPN_TARGET_MODE *pNewVidPnTargetModeInfo,
                                                const RTRECTSIZE *pResolution)
{
    pNewVidPnTargetModeInfo->Preference = D3DKMDT_MP_NOTPREFERRED;
    return vboxVidPnPopulateVideoSignalInfo(&pNewVidPnTargetModeInfo->VideoSignalInfo,
                                            pResolution, g_RefreshRate);
}

static void vboxVidPnPopulateSourceModeInfo(D3DKMDT_VIDPN_SOURCE_MODE *pNewVidPnSourceModeInfo,
                                            const RTRECTSIZE *pSize, D3DDDIFORMAT PixelFormat = D3DDDIFMT_A8R8G8B8)
{
    /* this is a graphics mode */
    pNewVidPnSourceModeInfo->Type = D3DKMDT_RMT_GRAPHICS;
    pNewVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx = pSize->cx;
    pNewVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy = pSize->cy;
    pNewVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize =
                        pNewVidPnSourceModeInfo->Format.Graphics.PrimSurfSize;
    pNewVidPnSourceModeInfo->Format.Graphics.Stride = pSize->cx * 4;
    pNewVidPnSourceModeInfo->Format.Graphics.PixelFormat = PixelFormat;
    pNewVidPnSourceModeInfo->Format.Graphics.ColorBasis = D3DKMDT_CB_SRGB;
    if (pNewVidPnSourceModeInfo->Format.Graphics.PixelFormat == D3DDDIFMT_P8) {
        pNewVidPnSourceModeInfo->Format.Graphics.PixelValueAccessMode = D3DKMDT_PVAM_SETTABLEPALETTE;
    } else {
        pNewVidPnSourceModeInfo->Format.Graphics.PixelValueAccessMode = D3DKMDT_PVAM_DIRECT;
    }
}

NTSTATUS VBoxVidPnRecommendFunctional(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPN hVidPn,
                                      const VBOXWDDM_RECOMMENDVIDPN *pData)
{
    const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
    NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(
                        hVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
    if (!NT_SUCCESS(Status)) {
        LOGE("DxgkCbQueryVidPnInterface failed Status(%#x)\n", Status);
        return Status;
    }

    VBOXCMDVBVA_SCREENMAP_DECL(UINT32, aVisitedSourceMap);
    memset(aVisitedSourceMap, 0, sizeof (aVisitedSourceMap));

    UINT32 Importance = (UINT32)D3DKMDT_VPPI_PRIMARY;

    for (UINT32 i = 0; i < (UINT32)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i) {
        INT32 iSource = pData->aTargets[i].iSource;
        if (iSource < 0) {
            continue;
        }

        if (iSource >= VBoxCommonFromDeviceExt(pDevExt)->cDisplays) {
            LOGE("invalid iSource:%u\n", iSource);
            return STATUS_INVALID_PARAMETER;
        }

        if (!pDevExt->fComplexTopologiesEnabled && iSource != (INT32)i) {
            LOGE("complex topologies not supported!\n");
            return STATUS_INVALID_PARAMETER;
        }

        bool fNewSource = false;

        if (!ASMBitTest(aVisitedSourceMap, iSource)) {
            int rc = VBoxWddmVModesAdd(pDevExt, i, &pData->aSources[iSource].Size, TRUE);
            if (RT_FAILURE(rc)) {
                LOGE("VBoxWddmVModesAdd failed %d\n", rc);
                return STATUS_UNSUCCESSFUL;
            }

            Status = vboxVidPnCheckMonitorModes(pDevExt, i);
            if (!NT_SUCCESS(Status)) {
                LOGE("vboxVidPnCheckMonitorModes failed %#x\n", Status);
                return Status;
            }

            ASMBitSet(aVisitedSourceMap, iSource);
            fNewSource = true;
        }

        Status = vboxVidPnPathAdd(hVidPn, pVidPnInterface,
                (const D3DDDI_VIDEO_PRESENT_SOURCE_ID)iSource, (const D3DDDI_VIDEO_PRESENT_TARGET_ID)i,
                (D3DKMDT_VIDPN_PRESENT_PATH_IMPORTANCE)Importance);
        if (!NT_SUCCESS(Status)) {
            LOGE("vboxVidPnPathAdd failed Status()0x%x\n", Status);
            return Status;
        }

        Importance++;

        do {
            D3DKMDT_HVIDPNTARGETMODESET hVidPnModeSet;
            const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnModeSetInterface;

            Status = pVidPnInterface->pfnCreateNewTargetModeSet(hVidPn,
                                i,
                                &hVidPnModeSet,
                                &pVidPnModeSetInterface);
            if (NT_SUCCESS(Status)) {
                D3DKMDT_VIDPN_TARGET_MODE *pVidPnModeInfo;
                Status = pVidPnModeSetInterface->pfnCreateNewModeInfo(hVidPnModeSet, &pVidPnModeInfo);
                if (NT_SUCCESS(Status)) {
                    vboxVidPnPopulateTargetModeInfo(pVidPnModeInfo, &pData->aSources[iSource].Size);
                    IN_CONST_D3DKMDT_VIDEO_PRESENT_TARGET_MODE_ID idMode = pVidPnModeInfo->Id;
                    Status = pVidPnModeSetInterface->pfnAddMode(hVidPnModeSet, pVidPnModeInfo);
                    if (NT_SUCCESS(Status)) {
                        pVidPnModeInfo = NULL;
                        Status = pVidPnModeSetInterface->pfnPinMode(hVidPnModeSet, idMode);
                        if (NT_SUCCESS(Status)) {
                            Status = pVidPnInterface->pfnAssignTargetModeSet(hVidPn, i, hVidPnModeSet);
                            if (NT_SUCCESS(Status)) {
                                LOGW("Recommended Target[%d] (%dx%d)\n", i,
                                     pData->aSources[iSource].Size.cx,
                                     pData->aSources[iSource].Size.cy);
                                break;
                            }
                            else {
                                LOGE("pfnAssignTargetModeSet failed %#x\n", Status);
                            }
                        }
                        else {
                            LOGE("pfnPinMode failed %#x\n", Status);
                        }
                    } else {
                        LOGE("pfnAddMode failed %#x\n", Status);
                    }

                    if (pVidPnModeInfo) {
                        pVidPnModeSetInterface->pfnReleaseModeInfo(hVidPnModeSet, pVidPnModeInfo);
                    }
                } else {
                    LOGE("pfnCreateNewTargetModeSet failed %#x\n", Status);
                }

                pVidPnInterface->pfnReleaseTargetModeSet(hVidPn, hVidPnModeSet);
            } else {
                LOGE("pfnCreateNewTargetModeSet failed %#x\n", Status);
            }

            return Status;
        } while (0);

        if (fNewSource) {
            do {
                D3DKMDT_HVIDPNSOURCEMODESET hVidPnModeSet;
                const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnModeSetInterface;

                Status = pVidPnInterface->pfnCreateNewSourceModeSet(hVidPn,
                                    iSource,
                                    &hVidPnModeSet,
                                    &pVidPnModeSetInterface);
                if (NT_SUCCESS(Status)) {
                    D3DKMDT_VIDPN_SOURCE_MODE *pVidPnModeInfo;
                    Status = pVidPnModeSetInterface->pfnCreateNewModeInfo(hVidPnModeSet, &pVidPnModeInfo);
                    if (NT_SUCCESS(Status)) {
                        vboxVidPnPopulateSourceModeInfo(pVidPnModeInfo, &pData->aSources[iSource].Size);
                        IN_CONST_D3DKMDT_VIDEO_PRESENT_SOURCE_MODE_ID idMode = pVidPnModeInfo->Id;
                        Status = pVidPnModeSetInterface->pfnAddMode(hVidPnModeSet, pVidPnModeInfo);
                        if (NT_SUCCESS(Status)) {
                            pVidPnModeInfo = NULL;
                            Status = pVidPnModeSetInterface->pfnPinMode(hVidPnModeSet, idMode);
                            if (NT_SUCCESS(Status)) {
                                Status = pVidPnInterface->pfnAssignSourceModeSet(hVidPn, iSource, hVidPnModeSet);
                                if (NT_SUCCESS(Status)) {
                                    LOGW("Recommended Source[%d] (%dx%d)\n", iSource, pData->aSources[iSource].Size.cx,
                                         pData->aSources[iSource].Size.cy);
                                    break;
                                } else {
                                    LOGE("pfnAssignSourceModeSet failed %#x\n", Status);
                                }
                            } else {
                                LOGE("pfnPinMode failed %#x\n", Status);
                            }
                        } else {
                            LOGE("pfnAddMode failed %#x\n", Status);
                        }

                        if (pVidPnModeInfo) {
                            pVidPnModeSetInterface->pfnReleaseModeInfo(hVidPnModeSet, pVidPnModeInfo);
                        }
                    } else {
                        LOGE("pfnCreateNewSourceModeSet failed %#x\n", Status);
                    }

                    pVidPnInterface->pfnReleaseSourceModeSet(hVidPn, hVidPnModeSet);
                } else {
                    LOGE("pfnCreateNewSourceModeSet failed %#x\n", Status);
                }

                return Status;
            } while (0);
        }
    }

    return STATUS_SUCCESS;
}

static D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE vboxVidPnCofuncModalityCurrentPathPivot(
        D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmPivot, const DXGK_ENUM_PIVOT *pPivot,
        D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
{
    switch (enmPivot) {
        case D3DKMDT_EPT_VIDPNSOURCE:
            if (pPivot->VidPnSourceId == VidPnSourceId) {
                return D3DKMDT_EPT_VIDPNSOURCE;
            }
            if (pPivot->VidPnSourceId == D3DDDI_ID_ALL) {
                return D3DKMDT_EPT_VIDPNSOURCE;
            }
            return D3DKMDT_EPT_NOPIVOT;
        case D3DKMDT_EPT_VIDPNTARGET:
            if (pPivot->VidPnTargetId == VidPnTargetId) {
                return D3DKMDT_EPT_VIDPNTARGET;
            }
            if (pPivot->VidPnTargetId == D3DDDI_ID_ALL) {
                return D3DKMDT_EPT_VIDPNTARGET;
            }
            return D3DKMDT_EPT_NOPIVOT;
        case D3DKMDT_EPT_SCALING:
        case D3DKMDT_EPT_ROTATION:
        case D3DKMDT_EPT_NOPIVOT:
            return D3DKMDT_EPT_NOPIVOT;
        default:
            LOGE("unexpected pivot\n");
            return D3DKMDT_EPT_NOPIVOT;
    }
}

static NTSTATUS vboxVidPnTargetModeSetToArray(D3DKMDT_HVIDPNTARGETMODESET hVidPnModeSet,
                    const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnModeSetInterface,
                    CR_SORTARRAY *pArray)
{
    VBOXVIDPN_TARGETMODE_ITER Iter;
    const D3DKMDT_VIDPN_TARGET_MODE *pVidPnModeInfo;

    VBoxVidPnTargetModeIterInit(&Iter, hVidPnModeSet, pVidPnModeSetInterface);

    while ((pVidPnModeInfo = VBoxVidPnTargetModeIterNext(&Iter)) != NULL) {
        RTRECTSIZE size;
        size.cx = pVidPnModeInfo->VideoSignalInfo.ActiveSize.cx;
        size.cy = pVidPnModeInfo->VideoSignalInfo.ActiveSize.cy;
        int rc = CrSaAdd(pArray, CR_RSIZE2U64(size));
        if (RT_FAILURE(rc)) {
            LOGE("CrSaAdd failed %d\n", rc);
            VBoxVidPnTargetModeIterTerm(&Iter);
            return STATUS_UNSUCCESSFUL;
        }
    }

    VBoxVidPnTargetModeIterTerm(&Iter);
    return VBoxVidPnTargetModeIterStatus(&Iter);
}

static NTSTATUS vboxVidPnCollectInfoForPathTarget(PVBOXMP_DEVEXT pDevExt,
        D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
        D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot, UINT32 *aAdjustedModeMap,
        CR_SORTARRAY *aModes, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
        D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
{
    const CR_SORTARRAY* pSupportedModes = VBoxWddmVModesGet(pDevExt, VidPnTargetId);
    NTSTATUS Status;
    if (enmCurPivot == D3DKMDT_EPT_VIDPNTARGET) {
        D3DKMDT_HVIDPNTARGETMODESET hVidPnModeSet;
        const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnModeSetInterface;
        Status = pVidPnInterface->pfnAcquireTargetModeSet(hVidPn,
                    VidPnTargetId,
                    &hVidPnModeSet,
                    &pVidPnModeSetInterface);
        if (!NT_SUCCESS(Status)) {
            LOGE("pfnAcquireTargetModeSet failed %#x\n", Status);
            return Status;
        }

        /* intersect modes from target */
        if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId)) {
            Status = vboxVidPnTargetModeSetToArray(hVidPnModeSet,
                        pVidPnModeSetInterface, &aModes[VidPnTargetId]);
            ASMBitSet(aAdjustedModeMap, VidPnTargetId);
        } else {
            CR_SORTARRAY Arr;
            CrSaInit(&Arr, 0);
            Status = vboxVidPnTargetModeSetToArray(hVidPnModeSet,
                     pVidPnModeSetInterface, &aModes[VidPnTargetId]);
            CrSaIntersect(&aModes[VidPnTargetId], &Arr);
            CrSaCleanup(&Arr);
        }

        pVidPnInterface->pfnReleaseTargetModeSet(hVidPn, hVidPnModeSet);

        if (!NT_SUCCESS(Status)) {
            LOGE("vboxVidPnTargetModeSetToArray failed 0x%x\n", Status);
            return Status;
        }

        return STATUS_SUCCESS;
    }

    RTRECTSIZE pinnedSize = {0};
    Status = vboxVidPnQueryPinnedTargetMode(hVidPn, pVidPnInterface, VidPnTargetId, &pinnedSize);
    if (!NT_SUCCESS(Status)) {
        LOGE("vboxVidPnQueryPinnedTargetMode failed 0x%x\n", Status);
        return Status;
    }

    if (pinnedSize.cx) {
        if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId)) {
            int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
            if (!RT_SUCCESS(rc)) {
                LOGE("CrSaAdd failed %d\n", rc);
                return STATUS_UNSUCCESSFUL;
            }
            ASMBitSet(aAdjustedModeMap, VidPnTargetId);
        } else {
            CrSaClear(&aModes[VidPnTargetId]);
            int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
            if (!RT_SUCCESS(rc)) {
                LOGE("CrSaAdd failed %d\n", rc);
                return STATUS_UNSUCCESSFUL;
            }
        }

        return STATUS_SUCCESS;
    }

    Status = vboxVidPnQueryPinnedSourceMode(hVidPn, pVidPnInterface, VidPnSourceId, &pinnedSize);
    if (!NT_SUCCESS(Status)) {
        LOGE("vboxVidPnQueryPinnedSourceMode failed 0x%x\n", Status);
        return Status;
    }

    if (pinnedSize.cx) {
        if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId)) {
            if (CrSaContains(pSupportedModes, CR_RSIZE2U64(pinnedSize))) {
                int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
                if (!RT_SUCCESS(rc)) {
                    LOGE("CrSaAdd failed %d\n", rc);
                    return STATUS_UNSUCCESSFUL;
                }
            }
            ASMBitSet(aAdjustedModeMap, VidPnTargetId);
        } else {
            CrSaClear(&aModes[VidPnTargetId]);
            if (CrSaContains(pSupportedModes, CR_RSIZE2U64(pinnedSize))) {
                int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
                if (!RT_SUCCESS(rc)) {
                    LOGE("CrSaAdd failed %d\n", rc);
                    return STATUS_UNSUCCESSFUL;
                }
            }
        }

        return STATUS_SUCCESS;
    }

    /* now we are here because no pinned info is specified,
     * we need to populate it based on the supported info
     * and modes already configured, this is pretty simple actually
     */
    if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId)) {
        int rc = CrSaClone(pSupportedModes, &aModes[VidPnTargetId]);
        if (!RT_SUCCESS(rc)) {
            LOGE("CrSaClone failed %d\n", rc);
            return STATUS_UNSUCCESSFUL;
        }
        ASMBitSet(aAdjustedModeMap, VidPnTargetId);
    } else {
        CrSaIntersect(&aModes[VidPnTargetId], pSupportedModes);
    }

    /* we are done */
    return STATUS_SUCCESS;
}

#define VBOXVIDPNDUMP_STRCASE(_t) \
        case _t: return #_t;
#define VBOXVIDPNDUMP_STRCASE_UNKNOWN() \
        default: return "Unknown";

const char* vboxVidPnDumpStrCFMPivotType(D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE EnumPivotType)
{
    switch (EnumPivotType)
    {
        VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_UNINITIALIZED);
        VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_VIDPNSOURCE);
        VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_VIDPNTARGET);
        VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_SCALING);
        VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_ROTATION);
        VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_NOPIVOT);
        VBOXVIDPNDUMP_STRCASE_UNKNOWN();
    }
}

void VBoxVidPnDumpCofuncModalityInfo(const char *pPrefix,
    D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmEnumPivotType,
    const DXGK_ENUM_PIVOT *pPivot, const char *pSuffix)
{
    LOGI("%sPivotType(%s), SourceId(0x%x), TargetId(0x%x),%s\n", pPrefix,
                        vboxVidPnDumpStrCFMPivotType(enmEnumPivotType),
                        pPivot->VidPnSourceId, pPivot->VidPnTargetId, pSuffix);
}

static NTSTATUS vboxVidPnSourceModeSetToArray(D3DKMDT_HVIDPNSOURCEMODESET hVidPnModeSet,
                    const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnModeSetInterface,
                    CR_SORTARRAY *pArray)
{
    VBOXVIDPN_SOURCEMODE_ITER Iter;
    const D3DKMDT_VIDPN_SOURCE_MODE *pVidPnModeInfo;

    VBoxVidPnSourceModeIterInit(&Iter, hVidPnModeSet, pVidPnModeSetInterface);

    while ((pVidPnModeInfo = VBoxVidPnSourceModeIterNext(&Iter)) != NULL) {
        RTRECTSIZE size;
        size.cx = pVidPnModeInfo->Format.Graphics.VisibleRegionSize.cx;
        size.cy = pVidPnModeInfo->Format.Graphics.VisibleRegionSize.cy;
        int rc = CrSaAdd(pArray, CR_RSIZE2U64(size));
        if (RT_FAILURE(rc)) {
            LOGE("CrSaAdd failed %d\n", rc);
            VBoxVidPnSourceModeIterTerm(&Iter);
            return STATUS_UNSUCCESSFUL;
        }
    }

    VBoxVidPnSourceModeIterTerm(&Iter);
    return VBoxVidPnSourceModeIterStatus(&Iter);
}

static NTSTATUS vboxVidPnCollectInfoForPathSource(PVBOXMP_DEVEXT pDevExt,
        D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
        D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot, UINT32 *aAdjustedModeMap,
        CR_SORTARRAY *aModes, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
        D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
{
    /* <- yes, modes are target-determined always */
    const CR_SORTARRAY* pSupportedModes = VBoxWddmVModesGet(pDevExt, VidPnTargetId);
    NTSTATUS Status;

    if (enmCurPivot == D3DKMDT_EPT_VIDPNSOURCE) {
        D3DKMDT_HVIDPNSOURCEMODESET hVidPnModeSet;
        const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnModeSetInterface;
        Status = pVidPnInterface->pfnAcquireSourceModeSet(hVidPn,
                    VidPnSourceId, &hVidPnModeSet, &pVidPnModeSetInterface);
        if (!NT_SUCCESS(Status)) {
            LOGE("pfnAcquireSourceModeSet failed 0x%x\n", Status);
            return Status;
        }

        /* intersect modes from target */
        if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId)) {
            Status = vboxVidPnSourceModeSetToArray(hVidPnModeSet,
                            pVidPnModeSetInterface, &aModes[VidPnTargetId]);
            ASMBitSet(aAdjustedModeMap, VidPnTargetId);
        } else {
            CR_SORTARRAY Arr;
            CrSaInit(&Arr, 0);
            Status = vboxVidPnSourceModeSetToArray(hVidPnModeSet,
                            pVidPnModeSetInterface, &aModes[VidPnTargetId]);
            CrSaIntersect(&aModes[VidPnTargetId], &Arr);
            CrSaCleanup(&Arr);
        }

        pVidPnInterface->pfnReleaseSourceModeSet(hVidPn, hVidPnModeSet);

        if (!NT_SUCCESS(Status)) {
            LOGE("pfnReleaseSourceModeSet failed 0x%x\n", Status);
            return Status;
        }

        /* intersect it with supported target modes, just in case */
        CrSaIntersect(&aModes[VidPnTargetId], pSupportedModes);

        return STATUS_SUCCESS;
    }

    RTRECTSIZE pinnedSize = {0};
    Status = vboxVidPnQueryPinnedSourceMode(hVidPn, pVidPnInterface, VidPnSourceId, &pinnedSize);
    if (!NT_SUCCESS(Status)) {
        LOGE("vboxVidPnQueryPinnedSourceMode failed 0x%x\n", Status);
        return Status;
    }

    if (pinnedSize.cx) {
        if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId)) {
            if (CrSaContains(pSupportedModes, CR_RSIZE2U64(pinnedSize))) {
                int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
                if (!RT_SUCCESS(rc)) {
                    LOGE("CrSaAdd failed %d\n", rc);
                    return STATUS_UNSUCCESSFUL;
                }
            }
            ASMBitSet(aAdjustedModeMap, VidPnTargetId);
        } else {
            CrSaClear(&aModes[VidPnTargetId]);
            if (CrSaContains(pSupportedModes, CR_RSIZE2U64(pinnedSize))) {
                int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
                if (!RT_SUCCESS(rc)) {
                    LOGE("CrSaAdd failed %d\n", rc);
                    return STATUS_UNSUCCESSFUL;
                }
            }
        }

        return STATUS_SUCCESS;
    }

    Status = vboxVidPnQueryPinnedTargetMode(hVidPn, pVidPnInterface, VidPnTargetId, &pinnedSize);
    if (!NT_SUCCESS(Status)) {
        LOGE("vboxVidPnQueryPinnedTargetMode failed 0x%x\n", Status);
        return Status;
    }

    if (pinnedSize.cx) {
        if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId)) {
            int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
            if (!RT_SUCCESS(rc)) {
                LOGE("CrSaAdd failed %d\n", rc);
                return STATUS_UNSUCCESSFUL;
            }
            ASMBitSet(aAdjustedModeMap, VidPnTargetId);
        }
        else {
            CrSaClear(&aModes[VidPnTargetId]);
            int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
            if (!RT_SUCCESS(rc)) {
                LOGE("CrSaAdd failed %d\n", rc);
                return STATUS_UNSUCCESSFUL;
            }
        }
        return STATUS_SUCCESS;
    }

    /* now we are here because no pinned info is specified, we need to populate it based on the supported info
     * and modes already configured,
     * this is pretty simple actually */
    if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId)) {
        int rc = CrSaClone(pSupportedModes, &aModes[VidPnTargetId]);
        if (!RT_SUCCESS(rc)) {
            LOGE("CrSaClone failed %d\n", rc);
            return STATUS_UNSUCCESSFUL;
        }
        ASMBitSet(aAdjustedModeMap, VidPnTargetId);
    } else {
        CrSaIntersect(&aModes[VidPnTargetId], pSupportedModes);
    }

    /* we are done */
    return STATUS_SUCCESS;
}

static NTSTATUS vboxVidPnTargetModeSetFromArray(D3DKMDT_HVIDPNTARGETMODESET hVidPnModeSet,
        const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnModeSetInterface,
        const CR_SORTARRAY *pArray)
{
    for (UINT32 i = 0; i < CrSaGetSize(pArray); ++i) {
        RTRECTSIZE size = CR_U642RSIZE(CrSaGetVal(pArray, i));

        D3DKMDT_VIDPN_TARGET_MODE *pVidPnModeInfo;
        NTSTATUS Status = pVidPnModeSetInterface->pfnCreateNewModeInfo(hVidPnModeSet, &pVidPnModeInfo);
        if (!NT_SUCCESS(Status)) {
            LOGE("pfnCreateNewModeInfo failed, Status 0x%x\n", Status);
            return Status;
        }

        LOGW("g_RefreshRate now is %d\n", g_RefreshRate);
        vboxVidPnPopulateTargetModeInfo(pVidPnModeInfo, &size);

        Status = pVidPnModeSetInterface->pfnAddMode(hVidPnModeSet, pVidPnModeInfo);
        if (!NT_SUCCESS(Status)) {
            LOGE("pfnAddMode (%d x %d) failed, Status 0x%x\n", size.cx, size.cy, Status);
            pVidPnModeSetInterface->pfnReleaseModeInfo(hVidPnModeSet, pVidPnModeInfo);
            continue;
        }
    }

    return STATUS_SUCCESS;
}

static NTSTATUS vboxVidPnApplyInfoForPathTarget(PVBOXMP_DEVEXT pDevExt,
        D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
        D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot, UINT32 *aAdjustedModeMap,
        const CR_SORTARRAY *aModes, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
        D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
{
    RT_NOREF(aAdjustedModeMap, VidPnSourceId);

    if (enmCurPivot == D3DKMDT_EPT_VIDPNTARGET) {
        return STATUS_SUCCESS;
    }

    RTRECTSIZE pinnedSize = {0};
    NTSTATUS Status = vboxVidPnQueryPinnedTargetMode(hVidPn, pVidPnInterface,
                                                     VidPnTargetId, &pinnedSize);
    if (!NT_SUCCESS(Status)) {
        LOGE("vboxVidPnQueryPinnedTargetMode failed 0x%x\n", Status);
        return Status;
    }

    if (pinnedSize.cx) {
        return STATUS_SUCCESS;
    }

    /* now just create the new source mode set and apply it */
    D3DKMDT_HVIDPNTARGETMODESET hVidPnModeSet;
    const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnModeSetInterface;
    Status = pVidPnInterface->pfnCreateNewTargetModeSet(hVidPn,
                        VidPnTargetId,
                        &hVidPnModeSet,
                        &pVidPnModeSetInterface);
    if (!NT_SUCCESS(Status)) {
        LOGE("pfnCreateNewTargetModeSet failed Status(0x%x)", Status);
        return Status;
    }

    Status = vboxVidPnTargetModeSetFromArray(hVidPnModeSet,
            pVidPnModeSetInterface,
            &aModes[VidPnTargetId]);
    if (!NT_SUCCESS(Status)) {
        LOGE("vboxVidPnTargetModeSetFromArray failed Status(0x%x)\n", Status);
        pVidPnInterface->pfnReleaseTargetModeSet(hVidPn, hVidPnModeSet);
        return Status;
    }

    Status = pVidPnInterface->pfnAssignTargetModeSet(hVidPn, VidPnTargetId, hVidPnModeSet);
    if (!NT_SUCCESS(Status)) {
        LOGE("\n\n!!!!!!!\n\n pfnAssignTargetModeSet failed, Status(0x%x)\n", Status);
        pVidPnInterface->pfnReleaseTargetModeSet(hVidPn, hVidPnModeSet);
        return Status;
    }

    Status = vboxVidPnCheckMonitorModes(pDevExt, VidPnTargetId, &aModes[VidPnTargetId]);

    if (!NT_SUCCESS(Status)) {
        LOGE("vboxVidPnCheckMonitorModes failed, Status(0x%x)\n", Status);
        return Status;
    }

    return STATUS_SUCCESS;
}

static NTSTATUS vboxVidPnSourceModeSetFromArray(D3DKMDT_HVIDPNSOURCEMODESET hVidPnModeSet,
        const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnModeSetInterface,
        const CR_SORTARRAY *pArray)
{
    for (UINT32 i = 0; i < CrSaGetSize(pArray); ++i) {
        RTRECTSIZE size = CR_U642RSIZE(CrSaGetVal(pArray, i));

        for (UINT32 m = 0; m < 2; ++m)
        {
            D3DKMDT_VIDPN_SOURCE_MODE *pVidPnModeInfo;
            NTSTATUS Status = pVidPnModeSetInterface->pfnCreateNewModeInfo(hVidPnModeSet, &pVidPnModeInfo);
            if (!NT_SUCCESS(Status)) {
                LOGE("pfnCreateNewModeInfo failed, Status 0x%x\n", Status);
                return Status;
            }

            vboxVidPnPopulateSourceModeInfo(pVidPnModeInfo, &size, m == 0 ? D3DDDIFMT_A8R8G8B8 : D3DDDIFMT_A8B8G8R8);

            Status = pVidPnModeSetInterface->pfnAddMode(hVidPnModeSet, pVidPnModeInfo);
            if (!NT_SUCCESS(Status)) {
                LOGE("pfnAddMode (%d x %d) failed, Status 0x%x\n", size.cx, size.cy, Status);
                pVidPnModeSetInterface->pfnReleaseModeInfo(hVidPnModeSet, pVidPnModeInfo);
                continue;
            }
        }
    }

    return STATUS_SUCCESS;
}

static NTSTATUS vboxVidPnApplyInfoForPathSource(PVBOXMP_DEVEXT pDevExt,
        D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
        D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot, UINT32 *aAdjustedModeMap,
        const CR_SORTARRAY *aModes, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
        D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
{
    RT_NOREF(pDevExt, aAdjustedModeMap);

    if (enmCurPivot == D3DKMDT_EPT_VIDPNSOURCE) {
        return STATUS_SUCCESS;
    }

    RTRECTSIZE pinnedSize = {0};
    NTSTATUS Status = vboxVidPnQueryPinnedSourceMode(hVidPn, pVidPnInterface, VidPnSourceId, &pinnedSize);
    if (!NT_SUCCESS(Status)) {
        LOGE("vboxVidPnQueryPinnedSourceMode failed 0x%x\n", Status);
        return Status;
    }

    if (pinnedSize.cx) {
        return STATUS_SUCCESS;
    }

    /* now just create the new source mode set and apply it */
    D3DKMDT_HVIDPNSOURCEMODESET hVidPnModeSet;
    const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnModeSetInterface;
    Status = pVidPnInterface->pfnCreateNewSourceModeSet(hVidPn,
                        VidPnSourceId,
                        &hVidPnModeSet,
                        &pVidPnModeSetInterface);
    if (!NT_SUCCESS(Status)) {
        LOGE("pfnCreateNewSourceModeSet failed Status(0x%x)\n", Status);
        return Status;
    }

    Status = vboxVidPnSourceModeSetFromArray(hVidPnModeSet,
            pVidPnModeSetInterface,
            &aModes[VidPnTargetId]); /* <- target modes always! */
    if (!NT_SUCCESS(Status)) {
        LOGE("vboxVidPnSourceModeSetFromArray failed Status(0x%x)\n", Status);
        pVidPnInterface->pfnReleaseSourceModeSet(hVidPn, hVidPnModeSet);
        return Status;
    }

    Status = pVidPnInterface->pfnAssignSourceModeSet(hVidPn, VidPnSourceId, hVidPnModeSet);
    if (!NT_SUCCESS(Status)) {
        LOGE("\n\n!!!!!!!\n\n pfnAssignSourceModeSet failed, Status(0x%x)\n", Status);
        pVidPnInterface->pfnReleaseSourceModeSet(hVidPn, hVidPnModeSet);
        return Status;
    }

    return STATUS_SUCCESS;
}

NTSTATUS VBoxVidPnCofuncModality(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPN hVidPn,
    D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmPivot, const DXGK_ENUM_PIVOT *pPivot)
{
    const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
    NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(hVidPn,
                        DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
    if (!NT_SUCCESS(Status)) {
        LOGE("DxgkCbQueryVidPnInterface failed Status()0x%x\n", Status);
        return Status;
    }

    D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
    const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
    Status = pVidPnInterface->pfnGetTopology(hVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
    if (!NT_SUCCESS(Status)) {
        LOGE("pfnGetTopology failed Status(0x%x)\n", Status);
        return Status;
    }

    VBOXVIDPN_PATH_ITER PathIter;
    const D3DKMDT_VIDPN_PRESENT_PATH * pPath;
    VBOXCMDVBVA_SCREENMAP_DECL(UINT32, aVisitedTargetMap);
    VBOXCMDVBVA_SCREENMAP_DECL(UINT32, aAdjustedModeMap);
    CR_SORTARRAY aModes[VBOX_VIDEO_MAX_SCREENS];

    memset(aVisitedTargetMap, 0, sizeof (aVisitedTargetMap));
    memset(aAdjustedModeMap, 0, sizeof (aAdjustedModeMap));
    memset(aModes, 0, sizeof (aModes));

    /* collect info first */
    VBoxVidPnPathIterInit(&PathIter, hVidPnTopology, pVidPnTopologyInterface);
    while ((pPath = VBoxVidPnPathIterNext(&PathIter)) != NULL) {
        D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId = pPath->VidPnSourceId;
        D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId = pPath->VidPnTargetId;
        /* actually vidpn topology should contain only one target info, right? */
        ASMBitSet(aVisitedTargetMap, VidPnTargetId);

        D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot = vboxVidPnCofuncModalityCurrentPathPivot(
                                                    enmPivot, pPivot, VidPnSourceId, VidPnTargetId);

        Status = vboxVidPnCollectInfoForPathTarget(pDevExt,
                hVidPn, pVidPnInterface, enmCurPivot, aAdjustedModeMap,
                aModes, VidPnSourceId, VidPnTargetId);
        if (!NT_SUCCESS(Status)) {
            LOGE("vboxVidPnCollectInfoForPathTarget failed Status(0x%x)\n", Status);
            VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
            break;
        }

        Status = vboxVidPnCollectInfoForPathSource(pDevExt,
                hVidPn,
                pVidPnInterface,
                enmCurPivot,
                aAdjustedModeMap,
                aModes,
                VidPnSourceId, VidPnTargetId);
        if (!NT_SUCCESS(Status)) {
            LOGE("vboxVidPnCollectInfoForPathSource failed Status(0x%x)\n", Status);
            VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
            break;
        }
    }

    VBoxVidPnPathIterTerm(&PathIter);

    if (!NT_SUCCESS(Status)) {
        goto done;
    }

    Status = VBoxVidPnPathIterStatus(&PathIter);
    if (!NT_SUCCESS(Status)) {
        LOGE("PathIter failed Status()0x%x\n", Status);
        VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
        goto done;
    }

    /* now we have collected all the necessary info,
     * go ahead and apply it */
    memset(aVisitedTargetMap, 0, sizeof (aVisitedTargetMap));
    VBoxVidPnPathIterInit(&PathIter, hVidPnTopology, pVidPnTopologyInterface);
    while ((pPath = VBoxVidPnPathIterNext(&PathIter)) != NULL) {
        D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId = pPath->VidPnSourceId;
        D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId = pPath->VidPnTargetId;
        /* actually vidpn topology should contain only one target info, right? */
        ASMBitSet(aVisitedTargetMap, VidPnTargetId);

        D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot = vboxVidPnCofuncModalityCurrentPathPivot(
                                                    enmPivot, pPivot, VidPnSourceId, VidPnTargetId);

        bool bUpdatePath = false;
        D3DKMDT_VIDPN_PRESENT_PATH AdjustedPath = {0};
        AdjustedPath.VidPnSourceId = pPath->VidPnSourceId;
        AdjustedPath.VidPnTargetId = pPath->VidPnTargetId;
        AdjustedPath.ContentTransformation = pPath->ContentTransformation;
        AdjustedPath.CopyProtection = pPath->CopyProtection;

        if (pPath->ContentTransformation.Scaling == D3DKMDT_VPPS_UNPINNED) {
            AdjustedPath.ContentTransformation.ScalingSupport.Identity = TRUE;
            bUpdatePath = true;
        }

        if (pPath->ContentTransformation.Rotation == D3DKMDT_VPPR_UNPINNED) {
            AdjustedPath.ContentTransformation.RotationSupport.Identity = TRUE;
            bUpdatePath = true;
        }

        if (bUpdatePath) {
            Status = pVidPnTopologyInterface->pfnUpdatePathSupportInfo(hVidPnTopology, &AdjustedPath);
            if (!NT_SUCCESS(Status)) {
                LOGE("pfnUpdatePathSupportInfo failed Status()0x%x\n", Status);
                VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
                goto done;
            }
        }

        Status = vboxVidPnApplyInfoForPathTarget(pDevExt,
                hVidPn,
                pVidPnInterface,
                enmCurPivot,
                aAdjustedModeMap,
                aModes,
                VidPnSourceId, VidPnTargetId);
        if (!NT_SUCCESS(Status)) {
            LOGE("vboxVidPnApplyInfoForPathTarget failed Status(0x%x\n", Status);
            VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
            break;
        }

        Status = vboxVidPnApplyInfoForPathSource(pDevExt,
                hVidPn, pVidPnInterface, enmCurPivot, aAdjustedModeMap,
                aModes, VidPnSourceId, VidPnTargetId);
        if (!NT_SUCCESS(Status)) {
            LOGE("vboxVidPnApplyInfoForPathSource failed Status(0x%x\n", Status);
            VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
            break;
        }
    }

    VBoxVidPnPathIterTerm(&PathIter);

    if (!NT_SUCCESS(Status)) {
        goto done;
    }

    Status = VBoxVidPnPathIterStatus(&PathIter);
    if (!NT_SUCCESS(Status)) {
        LOGE("PathIter failed Status()0x%x\n", Status);
        VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
        goto done;
    }

done:
    for (UINT32 i = 0; i < (UINT32)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i) {
        CrSaCleanup(&aModes[i]);
    }

    return Status;
}

NTSTATUS VBoxVidPnRecommendMonitorModes(PVBOXMP_DEVEXT pDevExt,
            D3DDDI_VIDEO_PRESENT_TARGET_ID VideoPresentTargetId,
            D3DKMDT_HMONITORSOURCEMODESET hVidPnModeSet,
            const DXGK_MONITORSOURCEMODESET_INTERFACE *pVidPnModeSetInterface)
{
    const CR_SORTARRAY *pSupportedModes = VBoxWddmVModesGet(pDevExt, VideoPresentTargetId);

    NTSTATUS Status = vboxVidPnMonitorModeSetFromArray(hVidPnModeSet,
                                pVidPnModeSetInterface, pSupportedModes);
    if (!NT_SUCCESS(Status)) {
        LOGE("vboxVidPnMonitorModeSetFromArray failed 0x%x\n", Status);
    }

    return Status;
}

void VBoxVidPnStTIterInit(PVBOXWDDM_SOURCE pSource, PVBOXWDDM_TARGET paTargets,
    UINT32 cTargets, VBOXWDDM_TARGET_ITER* pIter)
{
    pIter->pSource = pSource;
    pIter->paTargets = paTargets;
    pIter->cTargets = cTargets;
    pIter->i = 0;
    pIter->c = 0;
}

PVBOXWDDM_TARGET VBoxVidPnStTIterNext(VBOXWDDM_TARGET_ITER* pIter)
{
    PVBOXWDDM_SOURCE pSource = pIter->pSource;
    if (pSource->cTargets <= pIter->c) {
        return NULL;
    }

    int i = (!pIter->c) ? ASMBitFirstSet(pSource->aTargetMap, pIter->cTargets)
        : ASMBitNextSet(pSource->aTargetMap, pIter->cTargets, pIter->i);
    if (i < 0) {
        LOGE("Failed to find a target\n");
    }

    pIter->i = (UINT32)i;
    pIter->c++;
    return &pIter->paTargets[i];
}

void VBoxVidPnSourceCopy(VBOXWDDM_SOURCE *pDst, const VBOXWDDM_SOURCE *pSrc)
{
    UINT8 u8SyncState = pDst->u8SyncState;
    *pDst = *pSrc;
    pDst->u8SyncState &= u8SyncState;
}

void VBoxVidPnTargetCopy(VBOXWDDM_TARGET *pDst, const VBOXWDDM_TARGET *pSrc)
{
    UINT8 u8SyncState = pDst->u8SyncState;
    *pDst = *pSrc;
    pDst->u8SyncState &= u8SyncState;
}

void VBoxVidPnSourcesCopy(VBOXWDDM_SOURCE *pDst, const VBOXWDDM_SOURCE *pSrc, UINT32 cScreens)
{
    for (UINT32 i = 0; i < cScreens; ++i) {
        VBoxVidPnSourceCopy(&pDst[i], &pSrc[i]);
    }
}

void VBoxVidPnTargetsCopy(VBOXWDDM_TARGET *pDst, const VBOXWDDM_TARGET *pSrc, UINT32 cScreens)
{
    for (UINT32 i = 0; i < cScreens; ++i) {
        VBoxVidPnTargetCopy(&pDst[i], &pSrc[i]);
    }
}

void VBoxVidPnStTargetCleanup(PVBOXWDDM_SOURCE paSources, UINT32 cScreens,
                              PVBOXWDDM_TARGET pTarget)
{
    RT_NOREF(cScreens);

    if (pTarget->VidPnSourceId == D3DDDI_ID_UNINITIALIZED) {
        return;
    }

    PVBOXWDDM_SOURCE pSource = &paSources[pTarget->VidPnSourceId];
    if (!pSource) {
        return;
    }

    ASMBitClear(pSource->aTargetMap, pTarget->u32Id);
    pSource->cTargets--;
    pTarget->VidPnSourceId = D3DDDI_ID_UNINITIALIZED;

    pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_TOPOLOGY;
    pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_TOPOLOGY;
}

void VBoxVidPnStSourceCleanup(PVBOXWDDM_SOURCE paSources,
    D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
    PVBOXWDDM_TARGET paTargets, UINT32 cTargets)
{
    PVBOXWDDM_SOURCE pSource = &paSources[VidPnSourceId];
    VBOXWDDM_TARGET_ITER Iter;
    VBoxVidPnStTIterInit(pSource, paTargets, cTargets, &Iter);
    for (PVBOXWDDM_TARGET pTarget = VBoxVidPnStTIterNext(&Iter);
         pTarget; pTarget = VBoxVidPnStTIterNext(&Iter)) {
        VBoxVidPnStTargetCleanup(paSources, cTargets, pTarget);
        /* iterator is not safe wrt target removal, reinit it */
        VBoxVidPnStTIterInit(pSource, paTargets, cTargets, &Iter);
    }
}

NTSTATUS vboxVidPnSetupSourceInfo(PVBOXMP_DEVEXT pDevExt,
        CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo, PVBOXWDDM_ALLOCATION pAllocation,
        D3DDDI_VIDEO_PRESENT_SOURCE_ID  VidPnSourceId, VBOXWDDM_SOURCE *paSources)
{
    PVBOXWDDM_SOURCE pSource = &paSources[VidPnSourceId];

    /* pVidPnSourceModeInfo could be null if STATUS_GRAPHICS_MODE_NOT_PINNED,
     * see VBoxVidPnCommitSourceModeForSrcId
     */
    UINT8 fChanges = 0;
    if (pVidPnSourceModeInfo) {
        if (pSource->AllocData.SurfDesc.width != pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx) {
            fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
            pSource->AllocData.SurfDesc.width = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx;
        }
        if (pSource->AllocData.SurfDesc.height != pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy) {
            fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
            pSource->AllocData.SurfDesc.height = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy;
        }
        if (pSource->AllocData.SurfDesc.format != pVidPnSourceModeInfo->Format.Graphics.PixelFormat) {
            fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
            pSource->AllocData.SurfDesc.format = pVidPnSourceModeInfo->Format.Graphics.PixelFormat;
        }
        if (pSource->AllocData.SurfDesc.bpp != vboxWddmCalcBitsPerPixel(pVidPnSourceModeInfo->Format.Graphics.PixelFormat)) {
            fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
            pSource->AllocData.SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pVidPnSourceModeInfo->Format.Graphics.PixelFormat);
        }
        if(pSource->AllocData.SurfDesc.pitch != pVidPnSourceModeInfo->Format.Graphics.Stride) {
            fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
            pSource->AllocData.SurfDesc.pitch = pVidPnSourceModeInfo->Format.Graphics.Stride;
        }
        pSource->AllocData.SurfDesc.depth = 1;
        if (pSource->AllocData.SurfDesc.slicePitch != pVidPnSourceModeInfo->Format.Graphics.Stride) {
            fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
            pSource->AllocData.SurfDesc.slicePitch = pVidPnSourceModeInfo->Format.Graphics.Stride;
        }
        if (pSource->AllocData.SurfDesc.cbSize != pVidPnSourceModeInfo->Format.Graphics.Stride *
            pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy) {
            fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
            pSource->AllocData.SurfDesc.cbSize = pVidPnSourceModeInfo->Format.Graphics.Stride *
                                                 pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy;
        }

        if (g_VBoxDisplayOnly) {
            vboxWddmDmSetupDefaultVramLocation(pDevExt, VidPnSourceId, paSources);
        }
    } else {
        VBoxVidPnAllocDataInit(&pSource->AllocData, VidPnSourceId);
        fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_ALL;
    }

    if (!g_VBoxDisplayOnly)
    {
        vboxWddmAssignPrimary(pSource, pAllocation, VidPnSourceId);
    }

    pSource->u8SyncState &= ~fChanges;
    return STATUS_SUCCESS;
}

NTSTATUS vboxVidPnCommitSourceMode(PVBOXMP_DEVEXT pDevExt,
        CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo,
        PVBOXWDDM_ALLOCATION pAllocation,
        D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, VBOXWDDM_SOURCE *paSources)
{
    if (VidPnSourceId < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays) {
        return vboxVidPnSetupSourceInfo(pDevExt, pVidPnSourceModeInfo,
                                pAllocation, VidPnSourceId, paSources);
    }

    LOGE("invalid srcId (%d), cSources(%d)\n", VidPnSourceId,
         VBoxCommonFromDeviceExt(pDevExt)->cDisplays);

    return STATUS_INVALID_PARAMETER;
}

void VBoxVidPnStSourceTargetAdd(PVBOXWDDM_SOURCE paSources, UINT32 cScreens,
                        PVBOXWDDM_SOURCE pSource, PVBOXWDDM_TARGET pTarget)
{
    if (pTarget->VidPnSourceId == pSource->AllocData.SurfDesc.VidPnSourceId) {
        return;
    }

    VBoxVidPnStTargetCleanup(paSources, cScreens, pTarget);

    ASMBitSet(pSource->aTargetMap, pTarget->u32Id);
    pSource->cTargets++;
    pTarget->VidPnSourceId = pSource->AllocData.SurfDesc.VidPnSourceId;

    pTarget->fBlankedByPowerOff = RT_BOOL(pSource->bBlankedByPowerOff);
    LOGI("src %d and tgt %d are now blank %d\n",
         pSource->AllocData.SurfDesc.VidPnSourceId, pTarget->u32Id,
         pTarget->fBlankedByPowerOff);

    pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_TOPOLOGY;
    pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_TOPOLOGY;
}

typedef struct VBOXVIDPNCOMMITTARGETMODE
{
    NTSTATUS Status;
    D3DKMDT_HVIDPN hVidPn;
    const DXGK_VIDPN_INTERFACE* pVidPnInterface;
    VBOXWDDM_SOURCE *paSources;
    VBOXWDDM_TARGET *paTargets;
} VBOXVIDPNCOMMITTARGETMODE;

BOOLEAN vboxVidPnCommitTargetModeEnum(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology,
                                      const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
                                      CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
                                      D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId, SIZE_T cTgtPaths,
                                      PVOID pContext)
{
    RT_NOREF(hVidPnTopology, pVidPnTopologyInterface, cTgtPaths);

    VBOXVIDPNCOMMITTARGETMODE *pInfo = (VBOXVIDPNCOMMITTARGETMODE*)pContext;
    D3DKMDT_HVIDPNTARGETMODESET hVidPnTargetModeSet;
    CONST DXGK_VIDPNTARGETMODESET_INTERFACE* pVidPnTargetModeSetInterface;
    NTSTATUS Status = pInfo->pVidPnInterface->pfnAcquireTargetModeSet(pInfo->hVidPn, VidPnTargetId,
                                                &hVidPnTargetModeSet, &pVidPnTargetModeSetInterface);
    if (Status == STATUS_SUCCESS) {
        CONST D3DKMDT_VIDPN_TARGET_MODE* pPinnedVidPnTargetModeInfo;
        Status = pVidPnTargetModeSetInterface->pfnAcquirePinnedModeInfo(hVidPnTargetModeSet,
                                                                &pPinnedVidPnTargetModeInfo);
        if (Status == STATUS_SUCCESS) {
            VBOXWDDM_SOURCE *pSource = &pInfo->paSources[VidPnSourceId];
            VBOXWDDM_TARGET *pTarget = &pInfo->paTargets[VidPnTargetId];
            pTarget->Size.cx = pPinnedVidPnTargetModeInfo->VideoSignalInfo.ActiveSize.cx;
            pTarget->Size.cy = pPinnedVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cy;

            VBoxVidPnStSourceTargetAdd(pInfo->paSources, VBoxCommonFromDeviceExt(pDevExt)->cDisplays,
                                       pSource, pTarget);

            pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;

            pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pPinnedVidPnTargetModeInfo);
        } else {
            LOGE("pfnAcquirePinnedModeInfo failed Status(0x%x)\n", Status);
        }

        pInfo->pVidPnInterface->pfnReleaseTargetModeSet(pInfo->hVidPn, hVidPnTargetModeSet);
    } else {
        LOGE("pfnAcquireTargetModeSet failed Status(0x%x)\n", Status);
    }

    pInfo->Status = Status;
    return Status == STATUS_SUCCESS;
}

NTSTATUS VBoxVidPnCommitSourceModeForSrcId(PVBOXMP_DEVEXT pDevExt,
    const D3DKMDT_HVIDPN hDesiredVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
    PVBOXWDDM_ALLOCATION pAllocation, D3DDDI_VIDEO_PRESENT_SOURCE_ID  VidPnSourceId,
    VBOXWDDM_SOURCE *paSources, VBOXWDDM_TARGET *paTargets, BOOLEAN bPathPowerTransition)
{
    D3DKMDT_HVIDPNSOURCEMODESET hCurVidPnSourceModeSet;
    const DXGK_VIDPNSOURCEMODESET_INTERFACE *pCurVidPnSourceModeSetInterface;

    PVBOXWDDM_SOURCE pSource = &paSources[VidPnSourceId];
    NTSTATUS Status;

    if (bPathPowerTransition) {
        RTRECTSIZE PinnedModeSize;
        bool bHasPinnedMode;

        Status = vboxVidPnQueryPinnedSourceMode(hDesiredVidPn, pVidPnInterface,
                                                VidPnSourceId, &PinnedModeSize);
        bHasPinnedMode = Status == STATUS_SUCCESS && PinnedModeSize.cx > 0 && PinnedModeSize.cy > 0;
        pSource->bBlankedByPowerOff = !bHasPinnedMode;

        LOGI("Path power transition: srcId %d goes blank %d\n",
             VidPnSourceId, pSource->bBlankedByPowerOff);
    }

    VBOXWDDM_TARGET_ITER Iter;
    VBoxVidPnStTIterInit(pSource, paTargets, (UINT32)VBoxCommonFromDeviceExt(pDevExt)->cDisplays, &Iter);
    for (PVBOXWDDM_TARGET pTarget = VBoxVidPnStTIterNext(&Iter);
         pTarget; pTarget = VBoxVidPnStTIterNext(&Iter)) {
        pTarget->Size.cx = 0;
        pTarget->Size.cy = 0;
        pTarget->fBlankedByPowerOff = RT_BOOL(pSource->bBlankedByPowerOff);
        pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_ALL;
    }

    VBoxVidPnStSourceCleanup(paSources, VidPnSourceId, paTargets,
                             (UINT32)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);

    Status = pVidPnInterface->pfnAcquireSourceModeSet(hDesiredVidPn,
                VidPnSourceId,
                &hCurVidPnSourceModeSet,
                &pCurVidPnSourceModeSetInterface);
    if (Status == STATUS_SUCCESS) {
        CONST D3DKMDT_VIDPN_SOURCE_MODE* pPinnedVidPnSourceModeInfo;
        Status = pCurVidPnSourceModeSetInterface->pfnAcquirePinnedModeInfo(
                        hCurVidPnSourceModeSet, &pPinnedVidPnSourceModeInfo);
        if (Status == STATUS_SUCCESS) {
            Status = vboxVidPnCommitSourceMode(pDevExt, pPinnedVidPnSourceModeInfo,
                                               pAllocation, VidPnSourceId, paSources);
            if (Status == STATUS_SUCCESS) {
                D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
                CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
                Status = pVidPnInterface->pfnGetTopology(hDesiredVidPn,
                            &hVidPnTopology, &pVidPnTopologyInterface);
                if (Status == STATUS_SUCCESS) {
                    VBOXVIDPNCOMMITTARGETMODE TgtModeInfo = {0};
                    /* <- to ensure we're succeeded if no targets are set */
                    TgtModeInfo.Status = STATUS_SUCCESS;
                    TgtModeInfo.hVidPn = hDesiredVidPn;
                    TgtModeInfo.pVidPnInterface = pVidPnInterface;
                    TgtModeInfo.paSources = paSources;
                    TgtModeInfo.paTargets = paTargets;
                    Status = vboxVidPnEnumTargetsForSource(pDevExt, hVidPnTopology, pVidPnTopologyInterface,
                            VidPnSourceId, vboxVidPnCommitTargetModeEnum, &TgtModeInfo);
                    if (Status == STATUS_SUCCESS) {
                        Status = TgtModeInfo.Status;
                    } else if (Status == STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY) {
                        Status = STATUS_SUCCESS;
                    } else {
                        LOGE("vboxVidPnEnumTargetsForSource failed Status(0x%x)\n", Status);
                    }
                }
                else {
                    LOGE("pfnGetTopology failed Status(0x%x)\n", Status);
                }
            } else {
                LOGE("vboxVidPnCommitSourceMode failed Status(0x%x)\n", Status);
            }
            /* release */
            pCurVidPnSourceModeSetInterface->pfnReleaseModeInfo(hCurVidPnSourceModeSet, pPinnedVidPnSourceModeInfo);
        } else if (Status == STATUS_GRAPHICS_MODE_NOT_PINNED) {
            Status = vboxVidPnCommitSourceMode(pDevExt, NULL, pAllocation, VidPnSourceId, paSources);
        } else {
            LOGE("pfnAcquirePinnedModeInfo failed Status(0x%x)\n", Status);
        }

        pVidPnInterface->pfnReleaseSourceModeSet(hDesiredVidPn, hCurVidPnSourceModeSet);
    } else {
        LOGE("pfnAcquireSourceModeSet failed Status(0x%x)\n", Status);
    }

    return Status;
}

NTSTATUS vboxVidPnEnumTargetsForSource(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology,
        const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
        CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
        PFNVBOXVIDPNENUMTARGETSFORSOURCE pfnCallback, PVOID pContext)
{
    SIZE_T cTgtPaths;
    NTSTATUS Status = pVidPnTopologyInterface->pfnGetNumPathsFromSource(
                                hVidPnTopology, VidPnSourceId, &cTgtPaths);
    if (Status == STATUS_SUCCESS) {
        for (SIZE_T i = 0; i < cTgtPaths; ++i) {
            D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId;
            Status = pVidPnTopologyInterface->pfnEnumPathTargetsFromSource(
                            hVidPnTopology, VidPnSourceId, i, &VidPnTargetId);
            if (Status == STATUS_SUCCESS) {
                if (!pfnCallback(pDevExt, hVidPnTopology, pVidPnTopologyInterface,
                                 VidPnSourceId, VidPnTargetId, cTgtPaths, pContext)) {
                    break;
                }
            } else {
                LOGE("pfnEnumPathTargetsFromSource failed Status(0x%x)\n", Status);
                break;
            }
        }
    } else if (Status != STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY) {
        LOGE("pfnGetNumPathsFromSource failed Status(0x%x)\n", Status);
    }

    return Status;
}

void VBoxVidPnStCleanup(PVBOXWDDM_SOURCE paSources, PVBOXWDDM_TARGET paTargets, UINT32 cScreens)
{
    for (UINT i = 0; i < cScreens; ++i) {
        PVBOXWDDM_TARGET pTarget = &paTargets[i];
        VBoxVidPnStTargetCleanup(paSources, cScreens, pTarget);
    }
}

NTSTATUS VBoxVidPnCommitAll(PVBOXMP_DEVEXT pDevExt, const D3DKMDT_HVIDPN hDesiredVidPn,
        const DXGK_VIDPN_INTERFACE* pVidPnInterface, PVBOXWDDM_ALLOCATION pAllocation,
        VBOXWDDM_SOURCE *paSources, VBOXWDDM_TARGET *paTargets)
{
    D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
    const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
    NTSTATUS Status = pVidPnInterface->pfnGetTopology(hDesiredVidPn,
                            &hVidPnTopology, &pVidPnTopologyInterface);
    if (!NT_SUCCESS(Status)) {
        LOGE("pfnGetTopology failed Status 0x%x\n", Status);
        return Status;
    }

    for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i) {
        PVBOXWDDM_TARGET pTarget = &paTargets[i];
        pTarget->Size.cx = 0;
        pTarget->Size.cy = 0;
        pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_ALL;

        if (pTarget->VidPnSourceId == D3DDDI_ID_UNINITIALIZED) {
            continue;
        }

        VBOXWDDM_SOURCE *pSource = &paSources[pTarget->VidPnSourceId];
        VBoxVidPnAllocDataInit(&pSource->AllocData, pTarget->VidPnSourceId);
        pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_ALL;
    }

    VBoxVidPnStCleanup(paSources, paTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays);

    VBOXVIDPN_PATH_ITER PathIter;
    const D3DKMDT_VIDPN_PRESENT_PATH *pPath;
    VBoxVidPnPathIterInit(&PathIter, hVidPnTopology, pVidPnTopologyInterface);
    while ((pPath = VBoxVidPnPathIterNext(&PathIter)) != NULL) {
        Status = VBoxVidPnCommitSourceModeForSrcId(pDevExt, hDesiredVidPn,
                    pVidPnInterface, pAllocation, pPath->VidPnSourceId,
                    paSources, paTargets, FALSE);
        if (Status != STATUS_SUCCESS) {
            LOGE("VBoxVidPnCommitSourceModeForSrcId failed Status(0x%x)\n", Status);
            break;
        }
    }

    VBoxVidPnPathIterTerm(&PathIter);

    if (!NT_SUCCESS(Status)) {
        LOGE("VBoxVidPnCommitSourceModeForSrcId failed\n");
        return Status;
    }

    Status = VBoxVidPnPathIterStatus(&PathIter);
    if (!NT_SUCCESS(Status)) {
        LOGE("VBoxVidPnPathIterStatus failed Status 0x%x\n", Status);
        return Status;
    }

    return STATUS_SUCCESS;
}

void VBoxDumpSourceTargetArrays(VBOXWDDM_SOURCE *paSources, VBOXWDDM_TARGET *paTargets, UINT32 cScreens)
{
    for (UINT32 i = 0; i < cScreens; i++) {
       LOGW("source [%d] Sync 0x%x, cTgt %d, TgtMap0 0x%x, TgtRep %d, blanked %d\n",
            i, paSources[i].u8SyncState, paSources[i].cTargets, paSources[i].aTargetMap[0],
            paSources[i].fTargetsReported, paSources[i].bBlankedByPowerOff);

       LOGW("target [%d] Sync 0x%x, VidPnSourceId %d, blanked %d\n",
            i, paTargets[i].u8SyncState, paTargets[i].VidPnSourceId, paTargets[i].fBlankedByPowerOff);
    }
}
